#include "DA6208.h"
#include <cstdio>
#include <cstring>

DevMgr * dev_mgr_ptr=NULL;

DevMgr::DevMgr()
{
	for(int i=0;i<MAX_N_CARDS;i++)
		card_id[i]=-1;
}

I16 DevMgr::open_dev(U16 dev_num,U16 seq_num)
{
	if(seq_num>=MAX_N_CARDS)
		return ErrorSequenceNumberOutOfRange;
	else
	{
		if(card_id[seq_num]>=0) close_dev(card_id[seq_num]);
		card_id[seq_num]=Register_Card(PCI_6208V,dev_num);
		return card_id[seq_num];
	}
}
I16 DevMgr::close_dev(U16 seq_num)
{
	if(seq_num>=MAX_N_CARDS)
		return ErrorSequenceNumberOutOfRange;
	else
	{
		for(int i=seq_num*CHAN_PER_CARD;i<(seq_num+1)*CHAN_PER_CARD;i++)
			output(i,0.0);
		Release_Card(card_id[seq_num]);
		card_id[seq_num]=-1;
		return NoError;
	}
}
I16 DevMgr::output(U16 chan,F64 value)
{
	if(chan>=CHAN_PER_CARD*MAX_N_CARDS)
		return ErrorChannelNumberOutOfRange;
	else if(card_id[chan/CHAN_PER_CARD]<0)
		return ErrorCardNotRegistered;
	else
		return AO_VWriteChannel(card_id[chan/CHAN_PER_CARD],chan%CHAN_PER_CARD,max(MIN_V,min(value,MAX_V)));
}

int luaopen_DA6208(lua_State * L)
{
	dev_mgr_ptr=new DevMgr();
	static const luaL_reg da_lib[]={
		{"open",OpenDev},
		{"close",CloseDev},
		{"output",Output},
		{NULL,NULL}
	};
	luaL_register(L,"DA",da_lib);
	return 0;
}

int OpenDev(lua_State * L)
{
	I16 result=dev_mgr_ptr->open_dev(luaL_checkint(L,1),luaL_checkint(L,2));
	Sleep(100);
	if(result<0)
	{
		switch(result)
		{
		case ErrorTooManyCardRegistered:luaL_error(L,"Error occured while openning DA6208 device: ErrorTooManyCardRegistered");break;
		case ErrorUnknownCardType:luaL_error(L,"Error occured while openning DA6208 device: ErrorUnknownCardType");break;
		case ErrorOpenDriverFailed:luaL_error(L,"Error occured while openning DA6208 device: ErrorOpenDriverFailed");break;
		case ErrorOpenEventFailed:luaL_error(L,"Error occured while openning DA6208 device: ErrorOpenEventFailed");break;
		case ErrorSequenceNumberOutOfRange:luaL_error(L,"Error occured while openning DA6208 device: ErrorSequenceNumberOutOfRange");break;
		default:luaL_error(L,"Error occured while openning DA6208 device: ErrorUnknown");break;
		}
	}
	return 0;
}
int CloseDev(lua_State * L)
{
	I16 result=dev_mgr_ptr->close_dev(luaL_checkint(L,1));
	if(result<0)
	{
		switch(result)
		{
		case ErrorSequenceNumberOutOfRange:luaL_error(L,"Error occured while openning DA6208 device: ErrorSequenceNumberOutOfRange");break;
		default:luaL_error(L,"Error occured while openning DA6208 device: ErrorUnknown");break;
		}
	}
	return 0;
}
int Output(lua_State * L)
{
	I16 result=dev_mgr_ptr->output(luaL_checkint(L,1),luaL_checknumber(L,2));
	if(result<0)
	{
		switch(result)
		{
		case ErrorInvalidCardNumber:luaL_error(L,"Error occured while outputing votage device: ErrorInvalidCardNumber");break;
		case ErrorCardNotRegistered:luaL_error(L,"Error occured while outputing votage device: ErrorCardNotRegistered");break;
		case ErrorFuncNotSupport:luaL_error(L,"Error occured while outputing votage device: ErrorFuncNotSupport");break;
		case ErrorInvalidIoChannel:luaL_error(L,"Error occured while outputing votage device: ErrorInvalidIoChannel");break;
		case ErrorDaVoltageOutOfRange:luaL_error(L,"Error occured while outputing votage device: ErrorDaVoltageOutOfRange");break;
		case ErrorChannelNumberOutOfRange:luaL_error(L,"Error occured while outputing votage device: ErrorChannelNumberOutOfRange");break;
		default:luaL_error(L,"Error occured while outputing votage device: ErrorUnknown");break;
		}
	}
	return 0;
}